import {
  createWebHashHistory,
  createWebHistory,
  type RouterHistory,
  type RouteComponent,
  type RouteRecordRaw,
  type RouteRecordNormalized,
} from "vue-router";
import type { AsyncRouteType } from "@/api/routes";
import { getAsyncButton, getAsyncRoutes } from "@/api/routes";
import type { RouteConfigs } from "@/layout/types";
import { router, routes, constantMenus, remainingPaths } from "./index";
const IFrame = () => import("@/layout/FrameView.vue");
const Empty = () => import("@/views/empty/index.vue");
const MicroView = () => import("@/layout/MicroView.vue");

import {
  isAllEmpty,
  storageSession,
  intersection,
  cloneDeep,
  isUrl,
} from "@pureadmin/utils";
import { usePermissionStoreHook } from "@/stores/modules/permission";
import { sessionKey, type DataInfo } from "@/utils/auth";
import { buildHierarchyTree } from "@/utils/tree";
import { omit } from "lodash-unified";

const modulesRoutes = import.meta.glob("/src/views/**/*.{vue,tsx}"); // 读取所有views下的页面文件，采用懒加载的形式，支持代码分割
console.log(modulesRoutes, "modeldasd routeview");
function handRank(ramk: number, name: string, path: string) {
  return isAllEmpty(ramk) || (ramk === 0 && name !== "home" && path !== "/")
    ? true
    : false;
}
/** 按照路由中meta下的rank等级升序来排序路由 */
function ascending(arr: any[]) {
  arr.forEach((v, index) => {
    // 当rank不存在时，根据顺序自动创建，首页路由永远在第一位
    if (handRank(v?.meta?.rank, v.name, v.path)) v.meta.rank = index + 2;
  });
  return arr.sort(
    // NOTE: 如果后端返回权限路由，优先根据后端 sort 字段排序
    (
      a: { meta: { rank: number; sort?: number } },
      b: { meta: { rank: number; sort?: number } }
    ) => {
      if (a.meta?.sort && b.meta?.sort) {
        return a.meta.sort - b.meta.sort;
      } else {
        return a.meta.rank - b.meta.rank;
      }
    }
  );
}

/** 获取路由历史模式 https://next.router.vuejs.org/zh/guide/essentials/history-mode.html */
function getHistoryMode(): RouterHistory {
  const routerHistory = import.meta.env.VITE_ROUTER_HISTORY;
  const baseHistory = import.meta.env.VITE_BASE_URL;
  const historyMode = routerHistory.split(",");
  const leftMode = historyMode[0];
  // no param
  if (historyMode.length === 1) {
    if (leftMode === "hash") {
      return createWebHashHistory(baseHistory);
    } else if (leftMode === "h5") {
      return createWebHistory(baseHistory);
    }
  }
}

/** 判断两个数组彼此是否存在相同值 */
function isOneOfArray(a: Array<string>, b: Array<string>) {
  return Array.isArray(a) && Array.isArray(b)
    ? intersection(a, b).length > 0
      ? true
      : false
    : true;
}

/** 过滤meta中showLink为false的菜单 */
function filterTree(data: RouteComponent[]) {
  const newTree = cloneDeep(data).filter(
    (v: { meta: { showLink: boolean } }) => v.meta?.showLink !== false
  );
  newTree.forEach(
    (v: { children }) => v.children && (v.children = filterTree(v.children))
  );
  return newTree;
}

/** 过滤children长度为0的的目录，当目录下没有菜单时，会过滤此目录，目录没有赋予roles权限，当目录下只要有一个菜单有显示权限，那么此目录就会显示 */
function filterChildrenTree(data: RouteComponent[]) {
  const newTree = cloneDeep(data).filter((v: any) => v?.children?.length !== 0);
  newTree.forEach(
    (v: { children }) => v.children && (v.children = filterTree(v.children))
  );
  return newTree;
}

/** 从sessionStorage里取出当前登陆用户的角色roles，过滤无权限的菜单 */
function filterNoPermissionTree(data: RouteComponent[]) {
  const currentRoles =
    storageSession().getItem<DataInfo<number>>(sessionKey)?.roles;
  const newTree = cloneDeep(data).filter((v: any) =>
    isOneOfArray(v.meta?.roles, currentRoles)
  );
  newTree.forEach(
    (v: any) => v.children && (v.children = filterNoPermissionTree(v.children))
  );
  return filterChildrenTree(newTree);
}

/**
 * 将多级嵌套路由处理成一维数组
 * @param routesList 传入路由
 * @returns 返回处理后的一维路由
 */
function formatFlatteningRoutes(routesList: RouteRecordRaw[]): any[] {
  if (routesList.length === 0) return routesList;
  let hierarchyList = buildHierarchyTree(routesList);
  for (let i = 0; i < hierarchyList.length; i++) {
    if (hierarchyList[i].children) {
      hierarchyList = hierarchyList
        .slice(0, i + 1)
        .concat(hierarchyList[i].children, hierarchyList.slice(i + 1));
    }
  }
  return hierarchyList;
}

/**
 * 一维数组处理成多级嵌套数组（三级及以上的路由全部拍成二级，keep-alive 只支持到二级缓存）
 * @param routesList 处理后的一维路由菜单数组
 * @returns 返回将一维数组重新处理成规定路由的格式
 */
function formatTwoStageRoutes(routesList: RouteRecordRaw[]) {
  if (routesList.length === 0) return routesList;
  const newRoutesList: RouteRecordRaw[] = [];
  routesList.forEach((v: RouteRecordRaw) => {
    if (v.path === "/") {
      newRoutesList.push({
        component: v.component,
        name: v.name,
        path: v.path,
        redirect: v.redirect,
        meta: v.meta,
        children: [],
      });
    } else {
      newRoutesList[0]?.children.push({ ...v });
    }
  });
  return newRoutesList;
}

/** 通过path获取父级路径 */
function getParentPaths(path: string, routes: RouteRecordRaw[]) {
  // 深度遍历查找
  function dfs(routes: RouteRecordRaw[], path: string, parents: string[]) {
    for (let i = 0; i < routes.length; i++) {
      const item = routes[i];
      // 找到path则返回父级path
      if (item.path === path) return parents;
      // children不存在或为空则不递归
      if (!item.children || !item.children.length) continue;
      // 往下查找时将当前path入栈
      parents.push(item.path);

      if (dfs(item.children, path, parents).length) return parents;
      // 深度遍历查找未找到时当前path 出栈
      parents.pop();
    }
    // 未找到时返回空数组
    return [];
  }

  return dfs(routes, path, []);
}

/** 查找对应path的路由信息 */
function findRouteByPath(path: string, routes: RouteRecordRaw[]) {
  let res = routes.find((item: { path: string }) => item.path == path);
  if (res) {
    return isProxy(res) ? toRaw(res) : res;
  } else {
    for (let i = 0; i < routes.length; i++) {
      if (
        routes[i].children instanceof Array &&
        routes[i].children.length > 0
      ) {
        res = findRouteByPath(path, routes[i].children);
        if (res) {
          return isProxy(res) ? toRaw(res) : res;
        }
      }
    }
    return null;
  }
}

function addPathMatch() {
  if (!router.hasRoute("pathMatch")) {
    router.addRoute({
      path: "/:pathMatch(.*)",
      name: "pathMatch",
      redirect: "/error/404",
    });
  }
}

/** 处理缓存路由（添加、删除、刷新） */
function handleAliveRoute(matched: RouteRecordNormalized[], mode?: string) {
  switch (mode) {
    case "add":
      matched.forEach((v) => {
        usePermissionStoreHook().cacheOperate({ mode: "add", name: v.name });
      });
      break;
    case "delete":
      usePermissionStoreHook().cacheOperate({
        mode: "delete",
        name: matched[matched.length - 1].name,
      });
      break;
    default:
      usePermissionStoreHook().cacheOperate({
        mode: "delete",
        name: matched[matched.length - 1].name,
      });
      useTimeoutFn(() => {
        matched.forEach((v) => {
          usePermissionStoreHook().cacheOperate({ mode: "add", name: v.name });
        });
      }, 100);
  }
}

/** 批量删除缓存路由(keepalive) */
function delAliveRoutes(delAliveRouteList: Array<RouteConfigs>) {
  delAliveRouteList.forEach((route) => {
    usePermissionStoreHook().cacheOperate({
      mode: "delete",
      name: route?.name,
    });
  });
}

/**
 * 废弃 ⚠️
 * @param remoteRoute 后端返回权限路由
 * @param wholeRoutes 本地所有业务路由
 * @param newRoutes 生成的新路由 template
 * @returns 根据权限生成的新路由
 */
const filterRouteByCode = (
  remoteRoute: AsyncRouteType[],
  wholeRoutes: RouteConfigsTable[],
  newRoutes: RouteConfigsTable[] = []
): RouteConfigsTable[] => {
  Array.isArray(remoteRoute) &&
    remoteRoute?.forEach((rRoute) => {
      // 取出第一次层匹配到的route
      const eqRoute = cloneDeep(
        wholeRoutes?.find((ar) => ar.name === rRoute.code)
      );
      if ((!rRoute?.children || rRoute.children.length === 0) && eqRoute) {
        eqRoute.children = [];
      }
      if (eqRoute) {
        eqRoute.sort = rRoute.sort;
      }
      // 如果该后端路由有 children && 有匹配到本地路由
      if (rRoute?.children?.length && eqRoute) {
        eqRoute.children = filterRouteByCode(
          rRoute?.children,
          eqRoute?.children
        );
      }
      if (eqRoute) {
        if (rRoute?.path.includes("?")) {
          const remoteMeta = rRoute?.path
            ?.split("?")?.[1]
            .split("&")
            ?.reduce((pre, cur) => {
              const key = cur?.split("=")?.[0];
              const value = cur?.split("=")?.[1];
              return { ...pre, [key]: value };
            }, {});
          eqRoute.meta = { ...eqRoute?.meta, ...remoteMeta };
        }
        newRoutes.push(eqRoute);
      }
    });
  return newRoutes;
};

type AsyncAuthRouteType = AsyncRouteType & RouteRecordRaw;
/** 过滤后端传来的动态路由 重新生成规范路由 */
function addAsyncRoutes(arrRoutes: AsyncRouteType[]) {
  if (!arrRoutes || !arrRoutes.length) return;
  const modulesRoutesKeys = Object.keys(modulesRoutes);
  const arrRoutesCloned = arrRoutes;
  arrRoutesCloned.forEach((v: AsyncAuthRouteType) => {
    // 将backstage属性加入meta，标识此路由为后端返回路由
    v.meta = {};
    if (!v.children) v.children = []; // 兼容没有子路由的菜单报错
    v.meta.backroute = true;
    // 父级的redirect属性取值：如果子级存在且父级的redirect属性不存在，默认取第一个子级的path
    if (v?.children && v.children.length && !v.redirect)
      v.redirect = v.children[0].path;
    // 后端返回的动态路由表 name 对应本地路由表的 title ｜ code 对应 本地生成路由表的 name
    v.meta.title = v.name;
    v.name = v.code;
    // TODO：获取后端图标 （通过 source 字段获取图标配置，本地提供图标 map 映射表）
    // NOTE: 配置是否显示父级菜单，主要用于嵌套单个子菜单的情况
    if (v.isOpen) {
      v.meta.showParent = true;
    }
    // NOTE: 别名采用 xx-nolayout 的格式，如果配置 `-nolayout` 则该菜单采用无布局模式
    if (v.alias?.split("-")?.[1] === "nolayout") {
      remainingPaths.push(v.path);
      v.meta.nolayout = true;
    }

    v.meta.showLink = v.showLink === false ? false : true;

    // NOTE: 提供 frameSrc 则应用 iframe 组件
    if (v.frameSrc) {
      // 配置了 iframe 嵌入地址的情况直接使用 iframe 组件
      v.component = IFrame;
      v.meta.frameLoading = v.frameLoading;
      v.meta.frameSrc = v.frameSrc;
    } else if (v.frame === true && !v.children.length) {
      v.component = MicroView;
      v.meta.frameSrc = v.path;
    } else if (isUrl(v.code)) {
      // NOTE：外链菜单
      v.component = Empty; // 随便给个组件防止被过滤
    } else {
      // 根据后端路由 path 进行匹配，跟本地 views 文件下的路径进行对应
      // eg: 后端路由 path： /systeam/user 就会匹配到本地文件 /src/views/system/user/index.vue，就会将对应组件动态 import 函数方法赋值给 component 字段
      const index = modulesRoutesKeys.findIndex((ev) => ev.includes(v.path));
      v.component = modulesRoutes[modulesRoutesKeys[index]];
    }
    // 递归处理子菜单
    if (v?.children && v.children.length) {
      addAsyncRoutes(v.children);
    }
  });
  return arrRoutesCloned;
}

const OMIT_FILED = [
  "action",
  "actionName",
  "alias",
  "category",
  "categoryName",
  "id",
  "isDeleted",
  "isOpen",
  "isOpenName",
  "parentId",
  "parentName",
  "remark",
  "hasChildren",
];
/** 深度优先遍历路由表，如果某一层有组件则返回 true，否则 false */
const hasDeepComponent = (children) => {
  let hasComp = false;
  if (children && Array.isArray(children)) {
    for (let i = 0; i < children.length; i++) {
      if (children[i]?.component) {
        hasComp = true;
        return hasComp;
      } else {
        hasComp = hasDeepComponent(children[i]?.children);
      }
    }
  }
  return hasComp;
};
/** 主要用于过滤未匹配到本地路由的后端路由 */
const deepFormatRoutes = (routes: AsyncAuthRouteType[], routeList: any[]) => {
  if (routes && Array.isArray(routes)) {
    routes.forEach((rRoute) => {
      const rRouteBack: any = omit(rRoute, OMIT_FILED); // 过滤字段
      // NOTE： 过滤没匹配到本地组件的菜单
      if (
        rRouteBack.component === undefined &&
        !hasDeepComponent(rRouteBack.children)
      )
        return;
      if (rRouteBack?.children && rRouteBack?.children.length) {
        rRouteBack.children = deepFormatRoutes(rRouteBack?.children, []);
      }
      routeList.push(rRouteBack);
    });
    return routeList;
  }
};

/** 防止过滤之后的排序错乱，校准重定向地址 */
const adjustRedirect = (routes: AsyncAuthRouteType[]) => {
  if (routes && Array.isArray(routes)) {
    routes.forEach((r) => {
      if (r.children && r.children.length) {
        r.redirect = r.children[0].path;
      }
      adjustRedirect(r.children);
    });
  }
};

/** 处理动态路由（后端返回的路由） */
function handleAsyncRoutes(routeList) {
  if (routeList.length === 0) {
    usePermissionStoreHook().handleWholeMenus(constantMenus);
  } else {
    const asyncRoutes = addAsyncRoutes(routeList) || [];
    console.log(asyncRoutes, "111");
    const asyncRoutesFormated = deepFormatRoutes(asyncRoutes, []); // 过滤 component 为空之后的路由
    console.log(asyncRoutesFormated, "222");
    adjustRedirect(asyncRoutesFormated); // 解决因 comp 过滤后 redirect 匹配不上的问题
    const accessRoutes = formatFlatteningRoutes(asyncRoutesFormated).filter(
      (r) => r.component !== undefined
    );
    console.log(accessRoutes, "accessRoutes");
    accessRoutes.forEach((v: AsyncAuthRouteType) => {
      // 防止重复添加路由
      if (
        router.options.routes[0].children.findIndex(
          (value) => value.path === v.path
        ) !== -1
      ) {
        // 修改 home 路由信息
        if (v.path === "/home") {
          const outHome = router.getRoutes().find((r) => r.path === "/");
          const cHome = router.getRoutes().find((r) => r.path === "/home");
          outHome.meta = v.meta;
          cHome.meta.title = v.meta.title;
          // TODO：获取后端图标 （通过 source 字段获取图标配置，本地提供图标 map 映射表）
        }
        return;
      } else {
        if (v.meta.nolayout) {
          router.addRoute(v);
        } else {
          router.addRoute("home", v);
          router.options.routes[0].children.push(v);
        }
      }
    });
    usePermissionStoreHook().handleWholeMenus(asyncRoutesFormated);
  }
  addPathMatch();
}
/** 处理纯静态路由的情况 */
function handleStaticRoutes() {
  usePermissionStoreHook().handleWholeMenus([]);
}

function initRouter() {
  return new Promise((resolve) => {
    const menuAndButtonAuthReq = [getAsyncRoutes(), getAsyncButton()];
    Promise.all(menuAndButtonAuthReq)
      .then((res) => {
        const authRoutes = res[0]?.data ?? [];
        const authButtonArr = res[1]?.data ?? [];
        handleAsyncRoutes(cloneDeep(authRoutes));
        // console.log(
        //   usePermissionStoreHook(),
        //   usePermissionStoreHook().wholeMenus,
        //   "routes"
        // );
        const menus = usePermissionStoreHook().wholeMenus; // 所有菜单
        if (menus.length) {
          // 默认跳转到第一个菜单
          if (menus[0].children?.length) {
            router.push(menus[0].children[0].path);
          } else {
            router.push(menus[0].path);
          }
        } else {
          router.push("/");
        }
        usePermissionStoreHook().setPermission(authButtonArr);
        resolve(router);
      })
      .catch((error) => {
        console.error(
          "🚀 ~ file: utils.ts:308 ~ returnnewPromise ~ error",
          error
        );
      });
  });
}

export {
  getHistoryMode,
  ascending,
  formatFlatteningRoutes,
  formatTwoStageRoutes,
  filterTree,
  filterNoPermissionTree,
  getParentPaths,
  findRouteByPath,
  initRouter,
  handleAliveRoute,
  delAliveRoutes,
  handleStaticRoutes,
};
